﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using MTO.Framework.DirectoryServices.AccountManagement.Interfaces;
using MTO.Framework.DirectoryServices.AccountManagement.Enums;

namespace MTO.Framework.DirectoryServices.AccountManagement.LDAP
{
    /// <summary>
    /// Objet représentant un objet active directory qui a pour class d'objet : "user"
    /// </summary>
    /// <remarks>Lorsqu'on communique a active Directory directement, les usagers sont tous de type "user". Dans un environemment AD LDS parcontre, les "user" sont les objet créer au niveau de AD LDS. Les usager AD synchronisé vers AD LDS sont plutôt des "userProxy" et doivent utilisé la classe LDAPUserProxy.</remarks>
    [DirectoryRdnPrefix("CN")]
    [DirectoryObjectClass("user")]
    internal class LDAPUserPrincipal : UserPrincipal, IUserAccount
    {
        private TypesUserAccounts type = TypesUserAccounts.Externe;

        public LDAPUserPrincipal(PrincipalContext context)
            : base(context)
        {
        }

        public LDAPUserPrincipal(PrincipalContext context, string samAccountName, string password, bool isEnabled)
            : base(context, samAccountName, password, isEnabled)
        {
        }

        public LDAPUserPrincipal(PrincipalContext context, IUserAccount userAccount)
            : base(context)
        {
            this.MapUserAccount(userAccount);
        }

        [DirectoryProperty("co")]
        public string Country
        {
            get
            {
                var values = ExtensionGet("co");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("co", value);
            }
        }

        [DirectoryProperty("department")]
        public string Department
        {
            get
            {
                var values = ExtensionGet("department");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("department", value);
            }
        }

        [DirectoryProperty("description")]
        public new string Description
        {
            get
            {
                var values = ExtensionGet("description");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("description", value);
                base.Description = value;
            }
        }

        [DirectoryProperty("displayName")]
        public new string DisplayName
        {
            get
            {
                var values = ExtensionGet("displayName");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("displayName", value);
                base.DisplayName = value;
            }
        }

        [DirectoryProperty("givenName")]
        public new string GivenName
        {
            get
            {
                var values = ExtensionGet("givenName");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("givenName", value);
                base.GivenName = value;
            }
        }

        [DirectoryProperty("homeDirectory")]
        public new string HomeDirectory
        {
            get
            {
                var values = ExtensionGet("homeDirectory");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("homeDirectory", value);
                //base.HomeDirectory = value;
            }
        }

        [DirectoryProperty("mail")]
        public string Mail
        {
            get
            {
                var values = ExtensionGet("mail");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("mail", value);
                base.EmailAddress = value;
            }
        }

        [DirectoryProperty("mailNickname")]
        public string MailNickname
        {
            get
            {
                var values = ExtensionGet("mailNickname");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("mailNickname", value);
            }
        }

        [DirectoryProperty("name")]
        public new string Name
        {
            get
            {
                var values = ExtensionGet("name");
                return values != null && values.Length > 0 ? values[0].ToString() : null;
            }
            set 
            { 
                ExtensionSet("name", value);
                base.Name = value;
            }
        }

        [DirectoryProperty("objectSid")]
        public string ObjectSid
        {
            get
            {
                return this.Sid.ToString();
            }
            set 
            {
            }
        }

        [DirectoryProperty("physicalDeliveryOfficeName")]
        public string PhysicalDeliveryOfficeName
        {
            get
            {
                var values = ExtensionGet("physicalDeliveryOfficeName");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("physicalDeliveryOfficeName", value);
            }
        }

        [DirectoryProperty("sAMAccountName")]
        public new string SamAccountName
        {
            get
            {
                var values = ExtensionGet("sAMAccountName");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("sAMAccountName", value);
                //base.SamAccountName = value;
                this.UserPrincipalName = value;
            }
        }

        [DirectoryProperty("sn")]
        public new string Surname
        {
            get
            {
                var values = ExtensionGet("sn");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("sn", value);
                base.Surname = value;
            }
        }

        [DirectoryProperty("userPrincipalName")]
        protected internal new string UserPrincipalName
        {
            get
            {
                var values = ExtensionGet("userPrincipalName");
                return (values != null && values.Length > 0) ? values[0].ToString() : null;
            }
            set
            {
                ExtensionSet("userPrincipalName", value);
                base.UserPrincipalName = value;
            }
        }

        public static new LDAPUserPrincipal FindByIdentity(PrincipalContext context, string identityValue)
        {
            return (LDAPUserPrincipal)FindByIdentityWithType(context, typeof(LDAPUserPrincipal), identityValue);
        }

        public static new LDAPUserPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
        {
            return (LDAPUserPrincipal)FindByIdentityWithType(context, typeof(LDAPUserPrincipal), identityType, identityValue);
        }

        public TypesUserAccounts TypeUserAccount
        {
            get { return this.type; }
            set { this.type = value; }
        }

        private void MapUserAccount(IUserAccount userAccount)
        {
            if (userAccount == null)
            {
                return;
            }

            if (userAccount.Country != null)
            {
                this.Country = userAccount.Country;
            }

            if (userAccount.Department != null)
            {
                this.Department = userAccount.Department;
            }

            if (userAccount.Description != null)
            {
                this.Description = userAccount.Description;
            }

            if (userAccount.DisplayName != null)
            {
                this.DisplayName = userAccount.DisplayName;
            }

            if (userAccount.GivenName != null)
            {
                this.GivenName = userAccount.GivenName;
            }

            if (userAccount.HomeDirectory != null)
            {
                this.HomeDirectory = userAccount.HomeDirectory;
            }

            if (userAccount.Mail != null)
            {
                this.Mail = userAccount.Mail;
            }

            if (userAccount.MailNickname != null)
            {
                this.MailNickname = userAccount.MailNickname;
            }

            if (userAccount.Name != null)
            {
                this.Name = userAccount.Name;
            }

            if (userAccount.PhysicalDeliveryOfficeName != null)
            {
                this.PhysicalDeliveryOfficeName = userAccount.PhysicalDeliveryOfficeName;
            }

            if (userAccount.SamAccountName != null)
            {
                this.SamAccountName = userAccount.SamAccountName;
            }

            if (userAccount.Surname != null)
            {
                this.Surname = userAccount.Surname;
            }
        }
    }
}
